<?php
// @formatter:off
/**
 * @file WCTagsHolder.php
 * @author Alejandro Dario Simi
 * @date $Date: 2013-06-07 02:16:25 +0000 (Fri, 07 Jun 2013) $
 *
 * $Id: WCTagsHolder.php 71 2013-06-07 02:16:25Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/tags/wcomix-1.0-BETA1/includes/holders/WCTagsHolder.php $
 */
// @formatter:on

require_once "{$wcPaths["includes-directory"]}/representations/WCTag.php";

/**
 * @class WCTagsHolder
 * This class is a holder for representations of table '%tags', in other
 * words, a holder for WCTag objects.
 */
class WCTagsHolder extends WCGHolder {
	/**
	 * @var WCTagsHolder Pointer to the singleton instance.
	 */
	protected static $_Instance;
	/**
	 * @var string Class name of the objects to be held.
	 */
	protected $_PropertiesItemClass = "WCTag";
	/**
	 * @var string This is the prefix of every column on the table
	 * '%tags'.
	 */
	protected $_PropertiesPrefix = "tag_";
	/**
	 * @var string This is the name of the table represented by WCTag
	 * objects. In this case, '%tags'.
	 */
	protected $_PropertiesTable = "tags";
	/** @var int */
	protected $_time;
	protected function __construct() {
		parent::__construct();

		$this->_time = time();
	}
	//
	// Public methods.
	public function addTagTo(WCTag &$tag, WCComic &$comic) {
		$out = false;

		if($tag->ok() && $comic->ok() && $tag->group == $comic->group) {
			$out = $tag->add($comic);
		}

		return $out;
	}
	public function addTagToDirectory(WCTag &$tag, WCDirectory &$directory) {
		$out = false;

		if($tag->ok() && $directory->ok() && $tag->group == $directory->group) {
			$out = $tag->addDirectory($directory);
		}

		return $out;
	}
	public function addTagToTag(WCTag &$tag, WCTag &$tagToAdd) {
		$out = false;

		if($tag->ok() && $tagToAdd->ok() && $tag->group == $tagToAdd->group) {
			$out = $tag->addTag($tagToAdd);
		}

		return $out;
	}
	public function createSpecialTags() {
		global $wcSpecialTags;
		global $wcGroupsHolder;

		foreach($wcGroupsHolder->groups() as $group) {
			foreach($wcSpecialTags as $name) {
				if(!$this->findItemByName($name, $group)) {
					$this->create($name, $group);
				}
			}
		}
	}
	/**
	 *
	 * @param WCGroup $group
	 * @param bool $noSpecials
	 * @return multitype:WCTag
	 */
	public function tags(WCGroup &$group, $noSpecials = false) {
		global $wcSpecialTags;

		$out = array();
		if(!$noSpecials) {
			foreach($wcSpecialTags as $name) {
				$tag = $this->itemByName($name, $group);
				if($tag) {
					$out[] = $tag;
				}
			}
		}

		$out = array_merge($out, $this->items($group));
		uasort($out, "WCTag::NameSort");

		return $out;
	}
	public function tagsOf(WCComic &$comic) {
		$out = array();

		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "select  distinct mem_tag\n";
			$query .= "from    {$this->_dbprefix}tag_members\n";
			$query .= "where   mem_group = :group\n";
			$query .= " and    mem_comic = :comic";

			$stmt = $this->_db->prepare($stmtId, $query);
		}

		$params = array(
			":group" => $comic->group,
			":comic" => $comic->id
		);

		if($stmt->execute($params)) {
			global $wcGroupsHolder;
			$group = $wcGroupsHolder->groupById($comic->group);
			foreach($stmt->fetchAll() as $row) {
				$tag = $this->item($row["mem_tag"], $group);
				if($tag) {
					$out[] = $tag;
				}
			}
		}
		uasort($out, "WCTag::NameSort");

		return $out;
	}
	public function tagsOfDirectory(WCDirectory $directory) {
		$out = array();

		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "select  distinct mem_tag\n";
			$query .= "from    {$this->_dbprefix}tag_members\n";
			$query .= "                inner join {$this->_dbprefix}_comics\n";
			$query .= "                        on (cmc_id = mem_comic)\n";
			$query .= "where   mem_group     = :group\n";
			$query .= " and    cmc_directoryid = :directory";

			$stmt = $this->_db->prepare($stmtId, $query);
		}

		$params = array(
			":group" => $directory->group,
			":directory" => $directory->id
		);

		if($stmt->execute($params)) {
			global $wcGroupsHolder;
			$group = $wcGroupsHolder->groupById($directory->group);
			foreach($stmt->fetchAll() as $row) {
				$tag = $this->item($row["mem_tag"], $group);
				if($tag) {
					$out[] = $tag;
				}
			}
		}
		uasort($out, "WCTag::NameSort");

		return $out;
	}
	public function tagsOfTag(WCTag &$tag) {
		$out = array();

		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "select  distinct mem.mem_tag as mem_tag\n";
			$query .= "from    wc_tag_members as mem\n";
			$query .= "                inner join (\n";
			$query .= "                        select mem_comic\n";
			$query .= "                        from    wc_tag_members\n";
			$query .= "                        where   mem_group = :group\n";
			$query .= "                         and mem_tag = :tag) as tmp\n";
			$query .= "                                on (tmp.mem_comic = mem.mem_comic)\n";
			$query .= "where   mem.mem_group =  :group\n";
			$query .= " and    mem.mem_tag   <> :tag";

			$stmt = $this->_db->prepare($stmtId, $query);
		}

		$params = array(
			":group" => $tag->group,
			":tag" => $tag->id
		);

		if($stmt->execute($params)) {
			global $wcGroupsHolder;
			$group = $wcGroupsHolder->groupById($tag->group);
			foreach($stmt->fetchAll() as $row) {
				$tag = $this->item($row["mem_tag"], $group);
				if($tag) {
					$out[] = $tag;
				}
			}
		}
		uasort($out, "WCTag::NameSort");

		return $out;
	}
	public function tagsLike($keywords, WCGroup &$group) {
		$out = array();

		// Seeking exact finds
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "select  *\n";
			$query .= "from    {$this->_dbprefix}tags\n";
			$query .= "where   tag_group = :group\n";
			$query .= " and    lower(tag_name) like :filter\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}

		$params = array(
			":group" => $group->id,
			":filter" => "%".strtolower($keywords)."%"
		);

		if($stmt->execute($params)) {
			foreach($stmt->fetchAll() as $row) {
				$tag = $this->item($row["tag_id"], $group);
				$out[] = $tag;
			}
		}
		uasort($out, "WCTag::NameSort");

		return $out;
	}
	//
	// Public class methods.
	/**
	 * This class method allows to get the sole instance of this holder.
	 *
	 * @return WCTagsHolder Returns the singleton instance of this
	 * class.
	 */
	public static function Instance() {
		//
		// Checking if there's no instance yet.
		if(!isset(self::$_Instance)) {
			$c = __CLASS__;
			//
			// Creating the sole instance.
			self::$_Instance = new $c();
		}
		//
		// Returning the class instance.
		return self::$_Instance;
	}
}
?>